#include "dtu_4g.h"
#include <QMessageBox>
#include <iostream>
#include <QDebug>
#include <cstring>

/* 在进行阿里云透传连接时接收到对应恢复时的操作 */
#define RECV_COM_OK_HANDLE(NEXT) do{                \
                                    this->config_recv_buf.clear();          \
                                    connect_next = NEXT;                       \
                                    emit aly_serianet_connect_signal(connect_next); \
                                 }while(false)

using std::cout;
using std::endl;
using std::strcmp;

bool dtu_4G::getIs_aly_serianet_connect() const
{
    return is_aly_serianet_connect;
}

/**
 * 重置并重启4G模块
*/
void dtu_4G::dtu_4g_reset()
{
    cout << "4GDTU dev reset" << endl;
    this->dev_reset = true;
    while (this->serialPort->bytesToWrite()) {
    }
    this->serialPort->write("+++");
    cout << "send reset data" << endl;
}

/* 默认构造函数 */
dtu_4G::dtu_4G(QObject *parent) : QObject(parent)
{
    
}

dtu_4G::dtu_4G(QString serialName, QObject *parent) : QObject(parent)
{
    //创建串口对象
    this->serialPort = new QSerialPort(serialName,this);
    //设置串口名称
    this->serialPort->setPortName(serialName);
    //设置波特率
    this->serialPort->setBaudRate(static_cast<qint32>(115200));
    //设置数据位数
    this->serialPort->setDataBits(QSerialPort::Data8);
    //设置奇偶校验
    this->serialPort->setParity(QSerialPort::NoParity);
    //设置停止位
    this->serialPort->setStopBits(QSerialPort::OneStop);
    //设置流控制
    this->serialPort->setFlowControl(QSerialPort::NoFlowControl);
    //打开串口
    if(!this->serialPort->open(QIODevice::ReadWrite))
    {
        QMessageBox::about(nullptr,"错误","串口无法打开，可能串口已经被占用");
    }
    //关联信号与槽
    connect(this->serialPort,&QSerialPort::readyRead,this,&dtu_4G::serialPortReadyRead);
    connect(this,&dtu_4G::aly_serianet_connect_signal,this,&dtu_4G::aly_serianet_connect_slots);
    connect(this,&dtu_4G::dev_reset_signal,this,&dtu_4G::dev_reset_slots);
}

dtu_4G::dtu_4G(QSerialPort *serialPort)
{
    this->serialPort = serialPort;
    //打开串口
    if(!this->serialPort->open(QIODevice::ReadWrite))
    {
        QMessageBox::about(nullptr,"错误","串口无法打开，可能串口已经被占用");
    }
    //关联信号与槽
    connect(this->serialPort,&QSerialPort::readyRead,this,&dtu_4G::serialPortReadyRead);
}

dtu_4G::~dtu_4G()
{
    this->serialPort->close();
}

/**
  @description:在阿里云透传模式下将数据上传到阿里云云平台连接的设备
  @param - message:上传的数据
*/
void dtu_4G::aliyun_serianet_pub_mes(QByteArray &message)
{
    if(this->is_aly_serianet_connect && !this->dev_reset)
    {
        while(this->serialPort->bytesToWrite()) {
        }
        this->serialPort->write(message);
    }
}

void dtu_4G::aliyun_serianet_pub_mes(const char *cstr)
{
    if(this->is_aly_serianet_connect && !this->dev_reset)
    {
        while(this->serialPort->bytesToWrite()) {
        }
        this->serialPort->write(cstr);
    }
}

/**
  @description:使用阿里云透传模式连接阿里云云平台
  @param - data:使用4GDTU模块连接阿里云云平台所需的信息
  @return:操作结果
*/
int dtu_4G::aliyun_serianet_connect(dtu_4G_aliyun_data &data)
{
    int ret = 0;
    QByteArray tmp;
    cout << "aliyun serianet connect" << endl;
    while(this->serialPort->bytesToWrite()) {
    }
    tmp = "+++";
    this->serialPort->write(tmp);
    this->aly_serianet_data = data;

    return ret;
}

/**
  @description:断开阿里云透传模式下与阿里云云平台设备的连接
  @return:操作结果
*/
int dtu_4G::aliyun_disconnect()
{
    this->dtu_4g_reset();
    emit aly_disconnect();
}

void dtu_4G::serialPortReadyRead()
{
    qint8 connect_next = 0;

//    cout << "dtu recv data sz: " << this->serialPort->bytesAvailable() << endl;
    this->config_recv_buf.append(this->serialPort->readAll().constData());
//    cout << "4GDTU data: " << this->config_recv_buf.constData() << endl;
//    qDebug() << this->config_recv_buf << endl;
    /* 进行阿里云连接 */
    if(!this->dev_reset && !this->is_aly_serianet_connect)
    {
        if(this->config_recv_buf == static_cast<QString>("atk"))
        {
            cout << "recv atk" << endl;
            RECV_COM_OK_HANDLE(0);
        }
        else if(this->config_recv_buf == static_cast<QString>("\r\nOK\r\n"))
        {
            cout << "recv OK" << endl;
            RECV_COM_OK_HANDLE(1);
        }
        else if(this->config_recv_buf == static_cast<QString>("AT+WORK=\"ALIYUN\"\r\n\r\nOK\r\n"))
        {
            cout << "recv WORK" << endl;
            RECV_COM_OK_HANDLE(2);
        }
        else if(this->config_recv_buf == QString::asprintf("AT+ALIPK=\"%s\"\r\n\r\nOK\r\n",this->aly_serianet_data.ProductKey.constData()))
        {
            cout << "recv ALIPK" << endl;
            RECV_COM_OK_HANDLE(3);
        }
        else if(this->config_recv_buf == QString::asprintf("AT+ALIDN=\"%s\"\r\n\r\nOK\r\n",this->aly_serianet_data.DeviceName.constData()))
        {
            cout << "recv ALIDN" << endl;
            RECV_COM_OK_HANDLE(4);
        }
        else if(this->config_recv_buf == QString::asprintf("AT+ALIDS=\"%s\"\r\n\r\nOK\r\n",this->aly_serianet_data.DeviceSecret.constData()))
        {
            cout << "recv ALIDS" << endl;
            RECV_COM_OK_HANDLE(5);
        }
        else if(this->config_recv_buf == QString::asprintf("AT+ALIRI=\"%s\"\r\n\r\nOK\r\n",this->aly_serianet_data.territory.constData()))
        {
            cout << "recv ALIRI" << endl;
            RECV_COM_OK_HANDLE(6);
        }
        else if(this->config_recv_buf == QString::asprintf("AT+ALISUB=\"%s\"\r\n\r\nOK\r\n",this->aly_serianet_data.Sub_Topic.constData()))
        {
            cout << "recv ALISUB" << endl;
            RECV_COM_OK_HANDLE(7);
        }
        else if(this->config_recv_buf == QString::asprintf("AT+ALIPUB=\"%s\"\r\n\r\nOK\r\n",this->aly_serianet_data.Pub_Topic.constData()))
        {
            cout << "recv ALIPUB" << endl;
            RECV_COM_OK_HANDLE(8);
        }
        else if(this->config_recv_buf == QString::asprintf("AT+ALICON=%s\r\n\r\nOK\r\n",this->aly_serianet_data.CON.constData()))
        {
            cout << "recv ALICON" << endl;
            RECV_COM_OK_HANDLE(9);
        }
        else if(this->config_recv_buf == static_cast<QString>("ATO\r\n\r\nOK\r\n"))
        {
            cout << "recv ATO" << endl;
            this->is_aly_serianet_connect = true;
            emit aly_serianet_connect_ok();
        }
    }
    /* 进行设备重启 */
    else if(this->dev_reset)
    {
        if(this->config_recv_buf == static_cast<QString>("atk"))
        {
            cout << "dev rst recv atk" << endl;
            this->config_recv_buf.clear();
            emit dev_reset_signal(0);
        }
        else if(this->config_recv_buf == static_cast<QString>("\r\nOK\r\n"))
        {
            cout << "dev rst recv OK" << endl;
            this->config_recv_buf.clear();
            emit dev_reset_signal(1);
        }
        else if(this->config_recv_buf == static_cast<QString>("AT+CONRST\r\n\r\nOK\r\n"))
        {
            cout << "dev rst recv CONRST" << endl;
            this->config_recv_buf.clear();
            emit dev_reset_signal(2);
        }
        else if(this->config_recv_buf == static_cast<QString>("AT+PWR\r\n\r\nOK\r\n"))
        {
            cout << "dev rst recv PWR" << endl;
            this->config_recv_buf.clear();
            this->dev_reset = false;
            emit dev_reset_ok_signal();
        }
    }
    /* 接收云平台数据 */
    else if(this->is_aly_serianet_connect)
    {
        cout << this->config_recv_buf.data() << endl;
        this->config_recv_buf.clear();
    }
}

/**
 * @description:阿里云透传模式连接阿里云
 * @param - state:连接进度
*/
void dtu_4G::aly_serianet_connect_slots(qint8 state)
{
    QByteArray send_data{};

    switch (state) {
    case 0 : send_data = "atk";
        break;
    case 1 : send_data = "AT+WORK=\"ALIYUN\"\r\n";
        break;
    case 2 : send_data = QString::asprintf("AT+ALIPK=\"%s\"\r\n",this->aly_serianet_data.ProductKey.constData()).toLatin1().data();
        break;
    case 3 : send_data = QString::asprintf("AT+ALIDN=\"%s\"\r\n",this->aly_serianet_data.DeviceName.constData()).toLatin1().data();
        break;
    case 4 : send_data = QString::asprintf("AT+ALIDS=\"%s\"\r\n",this->aly_serianet_data.DeviceSecret.constData()).toLatin1().data();
        break;
    case 5 : send_data = QString::asprintf("AT+ALIRI=\"%s\"\r\n",this->aly_serianet_data.territory.constData()).toLatin1().data();
        break;
    case 6 : send_data = QString::asprintf("AT+ALISUB=\"%s\"\r\n",this->aly_serianet_data.Sub_Topic.constData()).toLatin1().data();
        break;
    case 7 : send_data = QString::asprintf("AT+ALIPUB=\"%s\"\r\n",this->aly_serianet_data.Pub_Topic.constData()).toLatin1().data();
        break;
    case 8 : send_data = QString::asprintf("AT+ALICON=%s\r\n",this->aly_serianet_data.CON.constData()).toLatin1().data();
        break;
    case 9 : send_data = "ATO\r\n";
        break;
    }
    this->serialPort->write(send_data.constData());
}

/**
  * @description:设备重置和重启
  * @param - state:配置状态
*/
void dtu_4G::dev_reset_slots(qint8 state)
{
    QByteArray send_data{};

    switch (state) {
    case 0 : send_data = "atk";
        break;
    case 1 : send_data = "AT+CONRST\r\n";
        break;
    case 2 : send_data = "AT+PWR\r\n";
        break;
    }

    this->serialPort->write(send_data);
}
